<!--
 * @description: 地图显示
 * @fileName: index.vue
 * @author: ssr
 * @date: 2022-08-12 09:38:14
 * @version: V1.0.0
! -->
<script setup lang="ts">
import type {
  IControlInstance,
  IEntityInstance,
  IEntityObject,
  Position
} from "@@/apis/scn/type"
import type {
  IDrawCallback
} from "@@/utils/CustomCesium/CustomCesium"
import type { Cartesian3 } from "cesium"
import { useCesiumStore } from "@/pinia/stores/cesium"
import { useScenarioStore } from "@/pinia/stores/scenario"
import { saveControlInstance, saveEntityInstance } from "@@/apis/scn"
import {
  CustomViewer,
  DrawingType,
  MathUtils
} from "@@/utils/CustomCesium/CustomCesium"
import mitter from "@@/utils/mitter"
import NameUtils from "@@/utils/ScenarioEdit/NameUtils"
import * as Cesium from "cesium"
import { Color, ConstantProperty } from "cesium"
import { isEmpty } from "lodash-es"
import {
  computed,
  onBeforeUnmount,
  onMounted,
  ref,
  watch
} from "vue"

// 定义组件属性
interface Props {
  customViewer: CustomViewer | null
}

const props = defineProps<Props>()
const emit = defineEmits(["update:customViewer"])
// 引用和状态
const cesiumContainerRef = ref<HTMLElement | null>(null)
const cesiumStore = useCesiumStore()
const scenarioStore = useScenarioStore()

// 计算属性
const currentControlObj = computed(() => scenarioStore.currentControlObj)
const currentEntityTemp = computed(() => scenarioStore.currentEntityTemp)

// 保存实体
function handleSaveEntity(instance: IEntityInstance): Promise<string> {
  return new Promise((resolve, reject) => {
    saveEntityInstance(instance).then(({ data }) => {
      resolve(data)
    })
  })
}

// 更新颜色
function handleAddControl(res: IDrawCallback, controlName: string) {
  const drawingManager = cesiumStore.getCustomViewer?.drawingManager
  if (
    scenarioStore.scnId
    && scenarioStore.currentControlObj
    && drawingManager
    && scenarioStore.currentSide
  ) {
    const controlObj = scenarioStore.currentControlObj
    const positions = handleParsePosition(res.position)
    const controlInstance: IControlInstance = {
      id: "",
      scnId: scenarioStore.scnId,
      // 控制对象名称
      name: controlName,
      // 所属方
      side: scenarioStore.currentSide.id,
      // 所属方颜色
      sideColor: scenarioStore.currentSide.color,
      // 类型
      type: controlObj.value,
      cesiumId: res.id,
      cesiumPosition: res.position,
      path: JSON.stringify(positions),
      param: JSON.stringify(res.param),
      positions
    }

    // 保存数据
    handelSaveControl(controlInstance)
      .then((id: string) => {
        controlInstance.id = id
        scenarioStore.selectedObjList.push(controlInstance)

        // 更新左侧列表数据
        mitter.emit("updateSelectedControl")
      })
      .catch(() => {
        res.id && handleDeleteCesium(res.id)
      })
  }
}

// cesium坐标转换
function handleParsePosition(
  cesiumPosition: Cartesian3 | Cartesian3[]
): Position[] {
  const positions: Position[] = []
  if (cesiumStore.customViewer) {
    if (!Array.isArray(cesiumPosition)) {
      // 对象
      positions.push(
        MathUtils.car3ToGCS(
          cesiumStore.customViewer.viewer,
          cesiumPosition as Cartesian3
        ) as Position
      )
    } else {
      // 数组
      (cesiumPosition as Cartesian3[]).forEach((pos) => {
        cesiumStore.customViewer
        && positions.push(
          MathUtils.car3ToGCS(cesiumStore.customViewer.viewer, pos) as Position
        )
      })
    }
  }
  return positions
}

// 保存失败删除绘制
function handleDeleteCesium(id: string) {
  const drawingManager = cesiumStore.getCustomViewer?.drawingManager
  if (drawingManager) {
    drawingManager.clearById(id)
  }
}

// 保存数据
function handelSaveControl(instance: IControlInstance): Promise<string> {
  return new Promise((resolve, reject) => {
    saveControlInstance(instance).then(({ data }) => {
      resolve(data)
    })
  })
}

// 更新绘制
function handleUpdateControlCesium(
  id: string,
  controlName: string,
  type: DrawingType
) {
  const drawingManager = cesiumStore.getCustomViewer.drawingManager
  if (drawingManager && scenarioStore.currentSide) {
    const entity = drawingManager.getById(id)
    const color = Color.fromCssColorString(
      scenarioStore.currentSide.color
    )
    entity.label.text = controlName
    entity.label.fillColor = new ConstantProperty(color)

    switch (type) {
      case DrawingType.Point:
        entity.point.color = new ConstantProperty(color)
        break
      case DrawingType.Polyline:
        entity.polyline.material = color
        break
      case DrawingType.Rectangle:
        entity.rectangle.material = color.withAlpha(0.3)
        break
      case DrawingType.Polygon:
        entity.polygon.material = color.withAlpha(0.3)
        break
      case DrawingType.Circle:
        entity.ellipse.material = color.withAlpha(0.3)
        break
      case DrawingType.Ellipse:
        entity.ellipse.material = color.withAlpha(0.3)
        break
      default:
        break
    }
  }
}

// 绘制实体
watch(
  () => scenarioStore.currentEntityTemp,
  (val: IEntityObject | null) => {
    if (val) {
      if (
        cesiumStore.customViewer
        && val.id
        && scenarioStore.scnId
        && scenarioStore.currentSide
      ) {
        const entityName = NameUtils.getInstanceName(
          scenarioStore.selectedEntityList,
          val.assistIdentify
        )

        const entityInstance: IEntityInstance = {
          id: "",
          scnId: scenarioStore.scnId,
          basicInfo: {
            entityId: val.id,
            entityName,
            side: scenarioStore.currentSide.id,
            sideColor: scenarioStore.currentSide.color,
            entityType: val.entityPath
          },
          entityTypeObj: val.entityType
        }

        scenarioStore.drawEntityManager?.addEntity(
          entityInstance,
          (res: IDrawCallback) => {
            if (!isEmpty(res.result) && res.result === false) {
              // 绘制失败
              scenarioStore.setCurrentEntityTemp(null)
              return
            }

            entityInstance.cesiumId = res.id
            entityInstance.cesiumPosition = res.position

            const position
              = cesiumStore.customViewer
                && res.position
                && MathUtils.car3ToGCS(
                  cesiumStore.customViewer.viewer,
                  res.position
                )

            entityInstance.basicInfo.longitude = position?.longitude
            entityInstance.basicInfo.latitude = position?.latitude
            entityInstance.basicInfo.height = position?.height

            handleSaveEntity(entityInstance)
              .then((id: string) => {
                entityInstance.id = id
                scenarioStore.selectedEntityList.push(entityInstance)

                // 更新左侧列表数据
                mitter.emit("updateSelectedEntity")
                mitter.emit("EntityEditDialogShow", id)
              })
              .catch(() => {
                res.id
                && scenarioStore.drawEntityManager?.clearById(res.id)
              })

            // 绘制结束 保存实体
            scenarioStore.setCurrentEntityTemp(null)
          }
        )
      }
    }
  }
)

// 初始化drawingManager?.draw
watch(
  () => scenarioStore.currentControlObj,
  (val) => {
    if (val) {
      if (
        cesiumStore.customViewer
        && currentControlObj.value
        && scenarioStore.currentSide
      ) {
        const drawingManager = cesiumStore.getCustomViewer?.drawingManager
        const controlName = NameUtils.getControlName(
          scenarioStore.selectedObjList,
          val.name
        )

        drawingManager?.draw(
          val.value,
          controlName,
          scenarioStore.currentSide.color,
          (res: IDrawCallback) => {
            if (!isEmpty(res.result) && res.result === false) {
              // 绘制失败
              scenarioStore.currentControlObj = null
            } else {
              // 添加实例
              handleAddControl(res, controlName)
              // 绘制结束 保存实体
              scenarioStore.currentControlObj = null
            }
          }
        )
      }
    }
  }
)

// 组件挂载
onMounted(async () => {
  try {
    const container = document.getElementById("cesium-container")
    if (!container) {
      console.error("Cesium container not found")
      return
    }

    // 设置初始化视框
    const extent = Cesium.Rectangle.fromDegrees(90, -20, 110, 90)
    Cesium.Camera.DEFAULT_VIEW_RECTANGLE = extent

    const customViewer = new CustomViewer("cesium-container")
    // 实例化Map
    cesiumStore.setCustomViewer(customViewer)

    const position = Cesium.Cartesian3.fromDegrees(119, 25, 10000000)

    customViewer.viewer.camera.flyTo({
      destination: position
    })

    emit("update:customViewer", customViewer)
  } catch (error) {
    console.error("Failed to initialize Cesium:", error)
  }
})

// 组件销毁
onBeforeUnmount(() => {
  try {
    const customViewer: CustomViewer | null = cesiumStore.getCustomViewer
    customViewer?.viewer.entities.removeAll()
    customViewer?.viewer.dataSources.removeAll(true)
    customViewer?.viewer.destroy()
    scenarioStore.drawEntityManager = null
    cesiumStore.setCustomViewer(null)
  } catch (e) {
    console.error("Error cleaning up Cesium:", e)
  }
})
</script>

<template>
  <div id="cesium-container" ref="cesiumContainerRef" />
</template>

<style lang="scss">
#cesium-container {
  width: calc(100%);
  height: calc(100%);
  &.draw {
    cursor: pointer;
  }
}
</style>
